package org.computate.controller.filter;

import java.io.IOException;

import javax.mail.MessagingException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.computate.form.ComputateForm;
import org.computate.model.dao.Daos;
import org.computate.model.item.Model;
import org.computate.tool.ModelTool;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.itextpdf.text.DocumentException;


@Singleton
public class ComputateFormFilter extends HttpServlet implements Filter {
	
	@Inject private ModelTool modelTool;
	@Inject private Daos daos;
	
	private static final long serialVersionUID = -8034352870319851172L;

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)servletRequest;
		HttpServletResponse response = (HttpServletResponse)servletResponse;
		String submitParameter = request.getParameter("submit");
		Class<?> modelClass = null;
		
		if(submitParameter != null) {
			try {
				modelClass = Class.forName("org.computate.model.item." + submitParameter);
			} catch (ClassNotFoundException e) {
				// ignore if class not found
			}
		}
		
		if(modelClass != null) {
			try {
				String nameParam = request.getParameter(submitParameter + "_name");
				Model item = modelTool.add(request, response, submitParameter, nameParam);
				
				item.setName(nameParam);
				response.sendRedirect(StringUtils.substringBeforeLast(request.getRequestURI(), "Submit.jsp") + ".jsp");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else {
			action(request, response, filterChain);
			filterChain.doFilter(servletRequest, servletResponse);
		}
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String submitParameter = request.getParameter("submit");
		Class<?> modelClass = null;
		
		if(submitParameter != null) {
			try {
				modelClass = Class.forName("org.computate.model.item." + submitParameter);
			} catch (ClassNotFoundException e) {
				// ignore if class not found
			}
		}
		
		if(modelClass != null) {
			try {
				String nameParam = request.getParameter(submitParameter + "_name");
				Model item = modelTool.add(request, response, submitParameter, nameParam);
				String requestURI = request.getRequestURI();
				String formName = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(requestURI, "/"), "/");
				
				item.setName(nameParam);
				response.sendRedirect("/page/form/" + formName + "/" + formName + ".jsp");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else {
			action(request, response, null);
		}
	}

	@Override
	public ServletConfig getServletConfig() {
		return null;
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void init(ServletConfig arg0) throws ServletException {
	}
	
	public Class<?> getFormClass(String formName) {
		Class<?> result = null;
		
		if(formName != null) {
			try {
				result = Class.forName("org.computate.form." + formName);
			} catch (ClassNotFoundException e) {
				// return null
			}
		}
		
		return result;
	}
	
	public ComputateForm action(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
		String requestURI = request.getRequestURI();
		ComputateForm form = null;
		
		try {
			if(StringUtils.endsWith(requestURI, ".pdf")) {
				String formName = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(requestURI, ".pdf"), "/");
				
				form = submit(request, response, formName);
				filterPDF(request, response, form, formName);
			}
			else if(StringUtils.endsWith(requestURI, "Submit.jsp")) {
				String formName = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(requestURI, "Submit.jsp"), "/");
				
				form = submit(request, response, formName);
				filterSubmit(request, response, form, formName);
			}
			else {
				String formName = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(requestURI, ".jsp"), "/");
				
				form = view(request, response, formName);
				filterView(request, response, form, formName);
			}
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return form;
	}
	
	public ComputateForm submit(HttpServletRequest request, HttpServletResponse response, String formName) throws InstantiationException, IllegalAccessException {
		ComputateForm form = null;
		
		if(formName != null) {
			Class<?> formClass = getFormClass(formName);
			
			if(formClass != null) {
				form = (ComputateForm)formClass.newInstance();
				form.populateFields(daos);
				
				request.setAttribute("form", form);
				request.setAttribute("formName", formName);
				form.populateValues(request, daos);
			}
		}
		
		return form;
	}
	
	public ComputateForm view(HttpServletRequest request, HttpServletResponse response, String formName) throws InstantiationException, IllegalAccessException {
		Class<?> formClass = getFormClass(formName);
		ComputateForm form = null;
		
		if(formClass != null) {
			form = (ComputateForm)formClass.newInstance();
			
			request.setAttribute("form", form);
			request.setAttribute("formName", formName);
			form.populateFields(daos);
		}
		
		return form;
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}

	
	protected void filterView(HttpServletRequest request, HttpServletResponse response, ComputateForm computateForm, String formName) {
		
	}
	
	protected void filterSubmit(HttpServletRequest request, HttpServletResponse response, ComputateForm computateForm, String formName) {
		try {
			computateForm.submit(daos);
			if(request.getServerName().equals("localhost"))
				computateForm.downloadPdf(request, response, daos);
			else {
				computateForm.sendInEmail(request, response, daos);
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	protected void filterPDF(HttpServletRequest request, HttpServletResponse response, ComputateForm computateForm, String formName) {
		try {
			computateForm.downloadPdf(request, response, daos);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
